from rest_framework.views import APIView
from QQLoginTool.QQtool import OAuthQQ
from rest_framework.response import Response
from django.conf import settings
from rest_framework import status
from rest_framework_jwt.settings import api_settings
from apps.carts.utils import merge_cart_cookie_to_redis

from .models import OAuthQQUser
import logging

from .seralizers import QQauthSerializer
from .utils import generate_save_user_token

logger = logging.getLogger("django")


class QQauthUrlView(APIView):
    """拼接QQ登录网址"""

    def get(self, request):
        # 1、 提取前端传入的next参数记录用户从哪里跳转至login
        url_path = request.query_params.get("next", "/")
        # 2、利用QQ的登录SDK
        qq_auth = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            client_secret=settings.QQ_CLIENT_SECRET,
            redirect_uri=settings.QQ_REDIRECT_URI,
            state=url_path,
        )
        # 3、创建QQ登录工具对象
        login_url = qq_auth.get_qq_url()
        # 4、调用它里面的方法，拼接好QQ登录链接网址
        return Response({"login_url": login_url})


class QQAuthUserView(APIView):
    """QQ登录成功后的回调处理"""

    def get(self, request):
        # 1、获取前端传入的code
        # 2、创建QQ登录工具对象
        # 3、调用get_access_token(code)用code向code向服务器获取access_token
        # 4、调用get_open_id(access_token)用access_token向QQ服务器获取openid
        # 5、查询数据库看是否存在openid，有则直接登录，没有则返回JWT状态保持登录信息
        code = request.query_params.get("code")
        if not code:
            return Response({"message": "缺少code"}, status=status.HTTP_400_BAD_REQUEST)
        qq_auth = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            client_secret=settings.QQ_CLIENT_SECRET,
            redirect_uri=settings.QQ_REDIRECT_URI,
        )

        try:
            access_token = qq_auth.get_access_token(code)
            open_id = qq_auth.get_open_id(access_token)
        except Exception as e:
            logger.warning("QQ服务器不可用:{}".format(e))
            return Response(
                {"message": "QQ服务器不可用"}, status=status.HTTP_503_SERVICE_UNAVAILABLE
            )

        try:
            auth_qq_model = OAuthQQUser.objects.get(open_id=open_id)
        except OAuthQQUser.DoesNotExist:
            # 6.如果openid 没有绑定用户,把openid 加密之后响应给前端 ,让前端先暂存一会 等待绑定时使用
            access_token_openid = generate_save_user_token(open_id)
            return Response("access_token", access_token_openid)
        else:
            user = auth_qq_model.user
            # 生成JWT 状态保存 token
            jwt_payload_handler = (
                api_settings.JWT_PAYLOAD_HANDLER
            )  # 引用jwt中的叫jwt_payload_handler函数(生成payload)
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 函数引用 生成jwt

            payload = jwt_payload_handler(user)  # 根据user生成用户相关的载荷
            token = jwt_encode_handler(payload)  # 传入载荷生成完整的jwt
            # 创建响应对象
            response = Response(
                {"token": token, "username": user.username, "user_id": user.id}
            )
            merge_cart_cookie_to_redis(request, user, response)
            return Response(response)

    def post(self, request):
        """OpenId绑定用户"""
        # 1、创建序列化器进行反序列化
        serializer = QQauthSerializer(data=request.data)
        # 2、调用is_valid方法进行校验
        serializer.is_valid(raise_exception=True)
        # 3、调用序列化器的save方法
        user = serializer.save()
        # 4、绑定用户
        jwt_payload_handler = (
            api_settings.JWT_PAYLOAD_HANDLER
        )  # 引用jwt中的叫jwt_payload_handler函数(生成payload)
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 函数引用 生成jwt

        payload = jwt_payload_handler(user)  # 根据user生成用户相关的载荷
        token = jwt_encode_handler(payload)  # 传入载荷生成完整的jwt
        # 5、登录成功，生成JWT状态保持token
        response = Response({"token": token, "username": user.username, "user_id": user.id})
        merge_cart_cookie_to_redis(request, user, response)
        return response
